package com.zhaozhe.querystatistic;

import java.util.*;

public class TopNPopularPathService implements TopNPopularPathServiceInterface {

    PathData pathData;
    @Override
    public void setup(String[][] data) {
        pathData = new PathData().getInstance();
        pathData.pathStrs = data;
    }

    @Override
    public String[] getTopNPopularPaths(int n) {
        String[][] pathsStrArray = pathData.pathStrs;
        Hashtable<String, String> userPathTable = new Hashtable<String, String>();
        Hashtable<String, Integer> pathsTable = new Hashtable<String, Integer>();

        //将原始数据格式化，userPathTable 是由用户 和 用户访问全量路径组成的哈希表
        for (int i = 0; i < pathsStrArray.length ; i++) {
            if (null == userPathTable.get(pathsStrArray[i][0])) {
                userPathTable.put(pathsStrArray[i][0], pathsStrArray[i][1]);
            } else {
                userPathTable.put(pathsStrArray[i][0], userPathTable.get(pathsStrArray[i][0]) + "->" + pathsStrArray[i][1]);
            }
        }

        //对userPathTable 做处理，将大于3步访问页面的访问路径拆分，拆分后再放入userPathTable
        Enumeration<String> e = userPathTable.keys();
        while (e.hasMoreElements()){
            String key = e.nextElement();
            Integer count = 0;
            String singlePath = userPathTable.get(key);

            if (appearNumber(singlePath, "->") > 2){
                userPathTable.remove(key);
                Hashtable<Integer, Integer> indexTable = new Hashtable<Integer, Integer>();
                int count1 = 0;
                int index = 0;
                indexTable.put(count1, 0);
                while ((index = singlePath.indexOf("->", index)) != -1) {
                    count1++;
                    indexTable.put(count1, index);
                    index = index + "->".length();
                }
                count1++;
                indexTable.put(count1, singlePath.length());
                Enumeration<Integer> e2 = indexTable.keys();
                while (e2.hasMoreElements()) {
                    Integer count2 = e2.nextElement();
                    for (int i = 0; i <= indexTable.size() - 4 ; i++){
                        String single3Path = "";
                        if (i == 0){
                            single3Path = singlePath.substring(indexTable.get(i), indexTable.get(i + 3));
                        } else {
                            single3Path = singlePath.substring(indexTable.get(i) + "->".length(), indexTable.get(i + 3));
                        }
                        userPathTable.put(key+"-"+i, single3Path);
                    }
                }
            }
        }

        //对3PagePath做初步统计，将结果放入pathsTable,pathsTable是由3PagePath和出现次数组成的哈希表
        Enumeration<String> e1 = userPathTable.keys();
        while (e1.hasMoreElements()){
            String key = e1.nextElement();
            String singlePath = userPathTable.get(key);
            Integer count = 0;
            if (null == pathsTable.get(singlePath)){
                pathsTable.put(singlePath, 1);
            } else {
                count = pathsTable.get(singlePath) + 1;
                pathsTable.put(singlePath, count);
            }
        }

        //将统计好数的pathsTable排序，打印出topN个数，返回包含出现最多的N个热门路径
        String[] topNPaths = new String[n];
        Map.Entry[] entries = sortHashTable(pathsTable);
        for (int i = 0; i < entries.length && i <= n ; i++){
            String topNPath = (String) entries[i].getKey();
            topNPaths[i] = topNPath;
            System.out.println(topNPath + " " + entries[i].getValue());
        }
        return topNPaths;
    }

    /**
     * public int indexOf(int ch, int fromIndex)
     * 返回在此字符串中第一次出现指定字符处的索引，从指定的索引开始搜索
     *
     * @param srcText
     * @param findText
     * @return
     */
    public static int appearNumber(String srcText, String findText) {
        int count = 0;
        int index = 0;
        while ((index = srcText.indexOf(findText, index)) != -1) {
            index = index + findText.length();
            count++;
        }
        return count;
    }

    /**
     * pathsTable排序
     * @param hashtable 待排序的哈希表
     */
    public Map.Entry[]  sortHashTable(Hashtable<String, Integer> hashtable){
        Map.Entry[] entries =  getSortedHashtableByValue(hashtable);
        return entries;
    }

    /**
     * 方法名称：getSortedHashtable
     * 参数：Hashtable h 引入被处理的散列表
     * 描述：将引入的hashtable.entrySet进行排序，并返回
     */
    public static Map.Entry[] getSortedHashtableByValue(Hashtable h) {
        Set set = h.entrySet();
        Map.Entry[] entries = (Map.Entry[]) set.toArray(new Map.Entry[set
                .size()]);

        Arrays.sort(entries, new Comparator() {
            public int compare(Object arg0, Object arg1) {
                int key1 = Integer.parseInt(((Map.Entry) arg0).getValue()
                        .toString());
                int key2 = Integer.parseInt(((Map.Entry) arg1).getValue()
                        .toString());
                return ((Comparable) key2).compareTo(key1);
            }
        });
        return entries;
    }

    public static void main(String[] args) {
        String[][] testData = new String[17][2];
        testData[0][1] = "/";
        testData[1][1] = "login";
        testData[2][1] = "subscriber";
        testData[0][0] = "U1";
        testData[1][0] = "U1";
        testData[2][0] = "U1";

        testData[3][1] = "/";
        testData[4][1] = "login";
        testData[5][1] = "subscriber";
        testData[3][0] = "U2";
        testData[4][0] = "U2";
        testData[5][0] = "U2";

        testData[6][1] = "/";
        testData[7][1] = "login";
        testData[8][1] = "product";
        testData[6][0] = "U3";
        testData[7][0] = "U3";
        testData[8][0] = "U3";

        testData[9][1] = "/";
        testData[9][0] = "U1";

        testData[10][1] = "/";
        testData[11][1] = "login";
        testData[12][1] = "product";
        testData[10][0] = "U4";
        testData[11][0] = "U4";
        testData[12][0] = "U4";

        testData[13][1] = "/";
        testData[14][1] = "login";
        testData[15][1] = "subscriber";
        testData[13][0] = "U5";
        testData[14][0] = "U5";
        testData[15][0] = "U5";

        testData[16][1] = "login";
        testData[16][0] = "U1";

        TopNPopularPathService pathService = new TopNPopularPathService();
        pathService.setup(testData);
        pathService.getTopNPopularPaths(4);

    }
}